package com.ridanlabs.professorwebsite.controller;

import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.google.appengine.api.blobstore.BlobInfo;
import com.google.appengine.api.blobstore.BlobInfoFactory;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreFailureException;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.blobstore.UnsupportedRangeFormatException;
import com.googlecode.objectify.Key;
import com.ridanlabs.professorwebsite.Util;
import com.ridanlabs.professorwebsite.models.Course;
import com.ridanlabs.professorwebsite.models.DAO;
import com.ridanlabs.professorwebsite.models.UserProfile;

@Controller
@PreAuthorize("hasRole('PROFESSOR')")
public class ProfessorController {
	private DAO dao = new DAO();
	private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
	private Logger logger = Logger.getLogger(ProfessorController.class.getName());
	private UserProfile user = Util.getAuthenticatedUser();
	
	@RequestMapping(value="/professor/index")
	public ModelAndView index() {
		ModelAndView mv = new ModelAndView("professor/index");
		
		if( user.getCourses() != null && !user.getCourses().isEmpty() ) {
			Map<Key<Course>, Course> courses =  dao.ofy().get( user.getCourses() );
			mv.addObject("courses", courses);
			mv.addObject("courseCount", courses.size());
		} else {
			mv.addObject("courseCount", 0);
		}
		
    	mv.addObject("user", user);
    	
		return mv;
	}
	
	@RequestMapping(value="/professor/course/{id}")
	public ModelAndView course(@PathVariable("id") String id) {
		BlobInfoFactory blobInfoFactory = new BlobInfoFactory();
		ModelAndView mv;
		
		Course course = dao.ofy().query(Course.class).filter("id", id).filter("courseProfessor", user).get();
		
		if( course == null ) {
			mv = new ModelAndView("error");
			mv.addObject("errorMessage", "Course Not Found");
			return mv;
		}
		
		String uploadUrl = "";
		try {
			uploadUrl = blobstoreService.createUploadUrl("/professor/course/" + id + "/notes/add");
		} catch (BlobstoreFailureException e) {
			logger.severe("Failed to created upload url: BlobstoreFailureException");
		}
		
		HashSet<BlobKey> courseNotesKeys = course.getNotes();
		LinkedList<BlobInfo> courseNotesInfos = new LinkedList<BlobInfo>();
		
		if( !courseNotesKeys.isEmpty() ) {
			for(BlobKey blobKey: courseNotesKeys) {
				courseNotesInfos.add( blobInfoFactory.loadBlobInfo(blobKey) );
			}
			
		} 
			
		mv = new ModelAndView("course/owner");
		
		mv.addObject("numOfNotes", courseNotesKeys.size());
		mv.addObject("notesInfos", courseNotesInfos);
		mv.addObject("course", course);
		mv.addObject("user", user);
		mv.addObject("notesUploadUrl", uploadUrl);
		
		return mv;
	}
	
	@RequestMapping(value="/professor/course/{id}/notes/add")
	public String addNotes(HttpServletRequest req, @PathVariable("id") String id) { //id corresponds to courseID - so we know which course we're adding it to
		BlobKey notesFileKey = null;
		
		try {
			Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(req);
			notesFileKey = blobs.get("notesFile");
		} catch(UnsupportedRangeFormatException e) {
			logger.severe("Error occured while uploading file: UnsupportedRangeFormatException");
		}
		
		if( notesFileKey != null ) {
			Course course = dao.ofy().query(Course.class).filter("id", id).filter("courseProfessor", user).get();
			
			if( course != null ) {
				course.insertNotesFile( notesFileKey );
				dao.saveCourse(course);
			}
				
		} else {
			logger.severe("Error of logical type: trying to upload notes with incorrect name attribute - UserId: " + user.getId());
		}
			
	    return "redirect:/professor/course/"+id; //as of now, the only confirmation of a success is by see if the new notes appear on the given course page
	}
	
	@RequestMapping(value="/professor/course/{id}/notes/{key}/*")
	public void serveNotes(HttpServletResponse res, @PathVariable("id") String id, @PathVariable("key") String key) {
		BlobKey notesKey = new BlobKey(key);
		
		try {
			blobstoreService.serve(notesKey, res);
		} catch (IOException e) {
			logger.severe("Error occured while trying to serve file for userId: " + user.getId() + "- IOException");
		}
	}
	
}
